#include "HostLink.h"


namespace cm_nat
{
    HostLink::HostLink( ByteBufferPool* p_pool, SocketReactor* reactor, BaseTimer* p_timer )
        :m_bufferPool(p_pool), m_reactor(reactor), 
        m_timer(p_timer),m_port(NULL),m_listener(NULL),
        m_agent(NULL)
    {

    }

    HostLink::~HostLink()
    {

    }

    int HostLink::setup( IPAddress host_ip )
    {
        bool res = false;

        if( !m_port ){
            m_port = new UDPPort(*m_reactor, m_bufferPool);
        }
        poco_assert( m_port != NULL );
        m_port->registerListener( this );

        res = m_port->setup( host_ip );

        //get host port number
        m_hostAddress = m_port->getHostAddress();
        poco_debug(g_log_nat, Logger::format("HostLink::host address:$0", m_hostAddress.toString()) );

        if( !m_agent ){
            m_agent = new StunAgent(m_bufferPool, m_timer);
        }
        poco_assert( m_agent != NULL );
        m_agent->registerListener( this );

        return true;

    }

    int HostLink::setup( NetworkInterface nic )
    {
        return setup( nic.address() );
    }
    
    int HostLink::teardown()
    {

        return 0;
    }

    void HostLink::registerListener( HostLinkListener* p_listener )
    {
        m_listener = p_listener;
    }

    SocketAddress HostLink::getHostAddress()
    {
        return m_hostAddress;
    }

    int HostLink::checkConnection(SocketAddress peer)
    {
        m_peerAddress = peer;

        m_agent->startCheck(m_peerAddress);

        return CM_RES_SUCCESS;
    }

    int HostLink::send( ByteBuffer* data )
    {
        if( m_port ){
            m_port->send( data, m_peerAddress );
            return CM_RES_SUCCESS;
        }

        return CM_RES_FAIL;
    }

    //from UDPPortListener
    void HostLink::onReceive(UDPPort*p_port, ByteBuffer* p_data)
    {
        bool res = false;

        if( m_agent ){
            res = m_agent->filterStunPacket( p_data );
        }

        if( !res && m_listener ){
            m_listener->onReceive( p_data );
        }
    }

    //from StunAgentListener
    void HostLink::onToSend(StunAgent* p_agent, ByteBuffer* data, SocketAddress sa)
    {
        m_port->send(data, sa);
    }

    void HostLink::onCheckResult(StunAgent* p_agent, int result)
    {
        if( StunAgentListener::CHECK_RES_CHECK_SUCCESS == result ){
            poco_debug(g_log_nat, "HostLink::onCheckResult Sucess" );
            p_agent->keepCheck();
        }else{
            poco_debug(g_log_nat, "HostLink::onCheckResult Fail" );
        }
    }

}